`define DELAY(N, clk) begin \
	repeat(N) @(posedge clk);\
	#1ps;\
end

module testbench();

//-------------------------------------{{{common cfg
timeunit 1ns;
timeprecision 1ps;
initial $timeformat(-9,3,"ns",6);

string tc_name;
int tc_seed;

initial begin
  if(!$value$plusargs("tc_name=%s", tc_name)) $error("no tc_name!");
  else $display("tc name = %0s", tc_name);
  if(!$value$plusargs("ntb_random_seed=%0d", tc_seed)) $error("no tc_seed");
  else $display("tc seed = %0d", tc_seed);
end
//-------------------------------------}}}

//-------------------------------------{{{parameter declare
parameter DL = 2;
parameter WD = 4;
parameter FF = 0;
//-------------------------------------}}}

//-------------------------------------{{{signal declare
logic  i_clk;
logic  i_rst_n;
logic [WD -1:0] i_data;
logic  i_en;
logic  i_ready;
logic  o_clk;
logic  o_rst_n;
logic [WD -1:0] o_data;
logic  o_en;
//-------------------------------------}}}

//-------------------------------------{{{clk/rst cfg
initial forever #5ns  i_clk = ~i_clk;
initial forever #12ns o_clk = ~o_clk;
initial begin
  i_rst_n = 1'b0;
  `DELAY(30, i_clk);
  i_rst_n = 1'b1;
end
initial begin
  o_rst_n = 1'b0;
  `DELAY(30, o_clk);
  o_rst_n = 1'b1;
end


bit sim_start; //valid/data drive while sim_start is HIGH
bit sim_finish;//sim_finish is HIGH, then #1000ns $finish, or #100000ns $finish from begin
bit sim_finish_ff, sim_finish_pulse;//use sim_finish_pulse to do something
initial begin
  sim_start  = 1'b0;
  sim_finish = 1'b0;
  wait(i_rst_n && o_rst_n);
  `DELAY(30, i_clk);
  sim_start  = 1'b1;
end

always @(posedge i_clk or negedge i_rst_n)begin
  if(!i_rst_n) sim_finish_ff <= 1'b0;
  else         sim_finish_ff <= sim_finish;
end
assign sim_finish_pulse = sim_finish && !sim_finish_ff;

initial begin
  fork
  #100000ns $finish; //fork0
  begin              //fork1
    wait(sim_finish == 1'b1);
    #1000ns $finish;
  end
  join_none
end
//-------------------------------------}}}

//-------------------------------------{{{valid sig assign
//-------------------------------------}}}

//-------------------------------------{{{ready sig assign
//-------------------------------------}}}

//-------------------------------------{{{data  sig assign
//-------------------------------------}}}

//-------------------------------------{{{other sig assign
initial begin
  i_data = $urandom;
  i_en = 1'b0;
  wait(sim_start);

  `DELAY(5, i_clk);
  i_en = 1'b1;
  i_data = $urandom;
  `DELAY(1, i_clk);
  //i_data = $urandom;
  //`DELAY(1, i_clk);
  i_en = 1'b0;
  i_data = $urandom;
  
  wait(i_ready == 1'b1);
  
  //`DELAY(5, i_clk);
  i_en = 1'b1;
  i_data = $urandom;
  `DELAY(1, i_clk);
  i_en = 1'b0;
  i_data = $urandom;
end

//-------------------------------------}}}

//-------------------------------------{{{rtl inst
async_nbit_hand #(
    .DL(DL),
    .WD(WD),
    .FF(FF)) 
u_async_nbit_hand(
    .i_clk(i_clk),
    .i_rst_n(i_rst_n),
    .i_data(i_data),
    .i_en(i_en),
    .i_ready(i_ready),
    .o_clk(o_clk),
    .o_rst_n(o_rst_n),
    .o_data(o_data),
    .o_en(o_en)
);

//-------------------------------------}}}

endmodule
